package com.woniuxy.carlife.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.carlife.domain.ServiceAppraise;
import com.woniuxy.carlife.domain.ServiceInfo;
import com.woniuxy.carlife.dto.AllAppraiseWithId;
import com.woniuxy.carlife.dto.AppraiseTagDto;
import com.woniuxy.carlife.dto.ServiceScoreDto;
import com.woniuxy.carlife.mapper.ServiceAppraiseMapper;
import com.woniuxy.carlife.minio.MinioTemplate;
import com.woniuxy.carlife.param.AppraiseParam;
import com.woniuxy.carlife.service.ServiceAppraiseService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author fx
 * @ClassName:ServiceAppraiseServiceImpl
 * @Description: 门店服务评价service实现类
 * @date 2021/4/6 20:00
 **/

@Service
public class ServiceAppraiseServiceImpl extends ServiceImpl<ServiceAppraiseMapper, ServiceAppraise> implements ServiceAppraiseService {

    @Resource
    private ServiceAppraiseMapper serviceAppraiseMapper;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private MinioTemplate mt;

    //这里还要调用feign接口获取用户信息

    /**
     * 功能描述〈用户根据用户id查询自己所有的评价,同时查询用户账号和头像对应的服务类别信息〉
     *
     * @throws
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/9 11:13
     */
    @Override
    public List<AllAppraiseWithId> findUserOwnAppraiseByUserId(Integer id) {
        List<AllAppraiseWithId> appraises = serviceAppraiseMapper.findAllAppraiseByUserId(id);
        //把取出来的标签字符串转为集合对象
        for (AllAppraiseWithId appraise : appraises) {
            if (!ObjectUtils.isEmpty(appraise.getCommentTag())){
                //有值就转换
                List<AppraiseTagDto> list = JSON.parseObject
                        (appraise.getCommentTag(), List.class);
                //设置值
                appraise.setAppraiseTag(list);
            }
        }
        if (ObjectUtils.isEmpty(appraises)) {
            return null;
        }
        //这里还要调用feign接口获取用户信息
        //并把用户的账号、头像赋值给这个dto对象再返回出去
        return appraises;
    }

    /**
     * 功能描述〈根据门店id查询对应门店的所有评论〉
     *
     * @throws
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/9 14:29
     */
    @Override
    public List<AllAppraiseWithId> findStoreAppraiseByStoreId(Integer storeId) {
        //先从redis中查询,查询所有storeid为指定门店id的评价
        List<String> appraise = redisTemplate
                .opsForList()
                .range("com.woniuxy:carlife:serviceproject:serviceappraise:storeid:" + storeId,
                        0, -1);
        //判断redis中是否有数据
        if (ObjectUtils.isEmpty(appraise)) {
            //redis没有数据就从数据库中查询
            List<AllAppraiseWithId> appraises =
                    serviceAppraiseMapper.findAllAppraiseByStoreId(storeId);
            //循环遍历这些评论再存到redis中
            for (AllAppraiseWithId appraise1 : appraises) {
                //把每个对象转换成json字符串存到redis中
                String str = JSON.toJSONString(appraise1);
                //存到redis
                redisTemplate.opsForList()
                        .leftPush("com.woniuxy:carlife:serviceproject:serviceappraise:storeid:" + storeId,
                                str);
            }
            //给这个key设置一个过期时间
            redisTemplate.expire("com.woniuxy:carlife:serviceproject:serviceappraise:storeid:" + storeId,
                    5, TimeUnit.MINUTES);
            //把结果返回出去
            return appraises;
        }
        //如果从reids中取到数据，转换数据
        //先声明个集合
        ArrayList<AllAppraiseWithId> allAppraise = new ArrayList<>();
        for (String s : appraise) {
            //把这些字符串转换成对象
            AllAppraiseWithId allAppraiseWithId = JSON.parseObject(s, AllAppraiseWithId.class);
            //存进集合
            allAppraise.add(allAppraiseWithId);
        }
        //把结果返回出去
        return allAppraise;
    }

    /**
     * 功能描述〈根据服务评价id查询对应服务评价详情〉
     *
     * @throws
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/9 14:44
     */
    @Override
    public ServiceAppraise findAppraiseInfoByAppraiseId(Integer serviceAppraiseId) {
        //查询评论详情对象并返回
        ServiceAppraise serviceAppraise =
                serviceAppraiseMapper.selectById(serviceAppraiseId);
        return serviceAppraise;
    }

    /**
     * 功能描述〈用户对指定的服务进行评价〉
     *
     * @throws
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/9 14:54
     */
    @Override
    public int saveAppraiseInfoToService(AppraiseParam appraiseParam) throws IOException {
        //先根据用户id、服务ID、订单id查询是否有数据，有就说明已经评论了
        QueryWrapper<ServiceAppraise> qq = new QueryWrapper<>();
        qq.eq("user_id",appraiseParam.getUserId());
        qq.eq("order_id",appraiseParam.getOrderId());
        qq.eq("service_id",appraiseParam.getServiceId());
        qq.eq("store_id",appraiseParam.getStoreId());
        //查询是否有数据
        ServiceAppraise serviceAppraise1 = serviceAppraiseMapper.selectOne(qq);
        if (!ObjectUtils.isEmpty(serviceAppraise1)){
            //如果有数据说明已经评论了
            return -1;
        }
        ServiceAppraise serviceAppraise = new ServiceAppraise();
        //设置评论的用户id
        serviceAppraise.setUserId(appraiseParam.getUserId());
        //设置评论的门店id
        serviceAppraise.setStoreId(appraiseParam.getStoreId());
        //设置评论的服务id
        serviceAppraise.setServiceId(appraiseParam.getServiceId());
        //订单id
        serviceAppraise.setOrderId(appraiseParam.getOrderId());
        //设置选择的评论标签dto对象集合
        //判断用户是否选择评论标签
        if (!ObjectUtils.isEmpty(appraiseParam.getAppraiseTag())) {
            //转换成json字符串
            String string = JSON.toJSONString(appraiseParam.getAppraiseTag());
            //设置到实体类的属性中
            serviceAppraise.setCommentTag(string);
        }
        //设置评分
        serviceAppraise.setServiceScore(appraiseParam.getServiceScore());
        //设置评论详情
        serviceAppraise.setServiceAppraiseInfo(appraiseParam.getServiceAppraiseInfo());
        //设置评论图片,现在传进来的是图片路径
        serviceAppraise.setServiceAppraisePic(appraiseParam.getPic());
        //设置创建时间
        serviceAppraise.setAppraiseCreateTime(new Timestamp(new Date().getTime()));
        //存储数据到数据库
        int insert = serviceAppraiseMapper.insert(serviceAppraise);
        if (insert > 0) {
            //针对指定服务添加并计算平均分，添加到reids，定时更新
            //先看redis有这个key没有
            String s = (String) redisTemplate.opsForValue()
                    .get("com.woniuxy:carlife:serviceproject:serviceappraisescore:serviceid:"
                            + appraiseParam.getServiceId());
            ServiceScoreDto score;
            if (ObjectUtils.isEmpty(s)){
                //声明统计平均分的dto类
                score = new ServiceScoreDto();
                //先设置默认数，总分为0
                score.setCommentsNum(0);
                score.setServiceScoreSum(0.0);
                score.setAverageScore(0.0);
                //如果没有就查评论表获得指定服务的所有评分
                List<ServiceAppraise> service_id = serviceAppraiseMapper.selectList
                        (new QueryWrapper<ServiceAppraise>()
                                .eq("service_id", appraiseParam.getServiceId()));
                //循环获得总评分、平均分
                for (ServiceAppraise appraise : service_id) {
                    int i=1;
                    //设置评论次数
                    score.setCommentsNum(i);
                    i++;
                    //设置总分
                    score.setServiceScoreSum(score.getServiceScoreSum()
                            +appraise.getServiceScore());
                }
            }else{
                //如果redis存在这个评分key
                //转对象
                score = JSON.parseObject(s, ServiceScoreDto.class);
                //设置评论次数
                score.setCommentsNum(score.getCommentsNum()+1);
                //设置总分
                score.setServiceScoreSum(score.getServiceScoreSum()
                        +appraiseParam.getServiceScore());

            }
            //计算平均分
            score.setAverageScore(score.getServiceScoreSum()/score.getCommentsNum());

            //取存的服务详情，把对应服务平均分更新
            String o = (String) redisTemplate.opsForValue()
                    .get("com.woniuxy:carlife:serviceproject:serviceinfo:id:"
                            + appraiseParam.getServiceId());
            ServiceInfo info = JSON.parseObject(o, ServiceInfo.class);
            info.setServiceScore(score.getServiceScoreSum()/score.getCommentsNum());
            String st = JSON.toJSONString(info);
            redisTemplate.opsForValue()
                    .set("com.woniuxy:carlife:serviceproject:serviceinfo:id:"
                            + appraiseParam.getServiceId(),st);

            //把这个对象更新到reids
            //转字符串
            String string = JSON.toJSONString(score);
            redisTemplate.opsForValue()
                    .set("com.woniuxy:carlife:serviceproject:serviceappraisescore:serviceid:"
                            + appraiseParam.getServiceId(),string);
            return 1;
        }
        return 0;
    }

    /**
     * 功能描述〈评论图片上传单独写〉
     *
     * @throws
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/13 2:06
     */
    @Override
    public String savaApprasiePic(List<MultipartFile> pics) throws IOException {
        //设置评论图片
        //先判断是否上传了图片
        if (!ObjectUtils.isEmpty(pics)) {
            //声明个String类型的集合存放图片路径
            ArrayList<String> picUrl = new ArrayList();
            for (int i = 0; i < pics.size(); i++) {
                MultipartFile file = pics.get(i);
                LocalDate id = LocalDate.now();
                StringBuffer fileName = new StringBuffer("/");
                fileName.append(id.getYear()).append("/")
                        .append(id.getMonthValue()).append("/")
                        .append(id.getDayOfMonth()).append("/")
                        .append(System.currentTimeMillis());
                String type = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
                fileName.append(type);
                //上传后返回路径
                String fourstage = mt.uploadFile(fileName.toString(), "fourstage", file.getInputStream(), file.getSize(), file.getContentType());
                //把路径放到集合中
                picUrl.add(fourstage);
            }
            //把存放了图片路径的集合转换为String类型
            String pic = JSON.toJSONString(picUrl);
            return pic;
        }else{
            return null;
        }
    }
}
